/**************************************************************************************
* 
*	Project Name : S3C6410 Validation
*
*	Copyright 2006 by Samsung Electronics, Inc.
*	All rights reserved.
*
*	Project Description :
*		This software is only for validating functions of the S3C6400.
*		Anybody can use this software without our permission.
*  
*--------------------------------------------------------------------------------------
* 
*	File Name : i2s.h
*  
*	File Description : This file defines the register access function
*						and declares prototypes of i2s funcions
*
*	Author : Sung-Hyun, Na
*	Dept. : AP Development Team
*	Created Date : 2008/03/04
*	Version : 0.2 
* 
*	History
*	- Created(Sung-Hyun, Na 2008/03/04)
*  
**************************************************************************************/
#ifndef __I2S_H__
#define __I2S_H__
 
  
#ifdef __cplusplus
extern "C" {
#endif

#include <stdio.h>
#include <sysc.h>
#include <dma.h>
#include <timer.h>
#include "def.h"
#include "audio.h"

#define I2S_BUFFER			(_DRAM_BaseAddress+100002C)
#define I2S_EXTERNALCLK		12288000
#define I2S_USERCLKOUT1		11289600
#define I2S_USERCLKOUT2		12288000
#define I2S_RECORD_LENGTH	0x3fff0
#define I2S_PLAY_LENGTH		0x3fff0
#define I2S_FIFOFlusDelay		100




#if 0 					//Struct for Regitster Read/Write Test
REGINFO		sRegInfo[] = 
{
	{"rI2S0CON					", I2S0_BASE+rI2SCON, 19, RW, DPDB, 0, 0x00000E00},   	
	{"rI2S0MOD					", I2S0_BASE+rI2SMOD, 14, RW, DPDB, 0, 0x00000000},   
	{"rI2S0FIC					", I2S0_BASE+rI2SFIC, 15, RW, DPDB, 0, 	0x00000000},   
	{"rI2S0PSR					", I2S0_BASE+rI2SPSR, 15, RW, DPDB, 0, 0x00000000},   
	{"rI2S0TXD					", I2S0_BASE+rI2STXD, 31, WO, DPDB, 0, 0x00000000},   
	{"rI2S0RXD					", I2S0_BASE+rI2SRXD, 31, RO, DPDB, 0, 0x00000000},   
		
	{"rI2S1CON					", I2S1_BASE+rI2SCON,  19, RW, DPDB, 0, 0x00000E00},   
	{"rI2S1MOD					", I2S1_BASE+rI2SMOD, 14, RO, DPDB, 0, 0x00000000},   
	{"rI2S1FIC					", I2S1_BASE+rI2SFIC, 15, RW, DPDB, 0, 0x00000000},   
	{"rI2S1PSR					", I2S1_BASE+rI2SPSR, 15, RW, DPDB, 0, 0x00000000},   
	{"rI2S1TXD					", I2S1_BASE+rI2STXD, 31, WO, DPDB, 0, 0x00000000},   
	{"rI2S1RXD					", I2S1_BASE+rI2SRXD, 31, RO, DPDB, 0, 0x00000000},   
};
#endif 




typedef enum
{
	Internal_CLK = 0,
	External_CLK = 1,
}I2S_CDCLKCon;

typedef enum
{
	I2S_MOUT_EPLL = 0,
	I2S_DOUT_MPLL = 1,
	I2S_FIN = 2,
	I2S_EXTERNALCDCLK = 3,	
	I2S_PCMEXT1	= 4,
	I2S_PCLK = 5,	
}I2S_CLKSRC;

typedef enum
{
	TXOnly = 0,
	RXOnly = 1,
	TXRXBoth = 2,
	TXRXNeither = 3,
}I2S_IFMode;

typedef enum
{
	RightHigh = 0,
	LeftHigh = 1,
}I2S_LRCLKPolarity;

typedef enum
{
	RFS_256fs = 0,		//8bit stereo
	RFS_512fs = 1,		//16bit stereo
	RFS_384fs = 2,		//12bit stereo
	RFS_768fs = 3, 		//24bit stereo
}I2S_RFS;				//RFS

typedef enum
{
	BFS_32fs = 0,			//16bit
	BFS_48fs = 1,			//24bit
	BFS_16fs = 2, 		//8bit
	BFS_24fs = 3,			//12bit
}I2S_BFS;				//BFS

typedef enum
{
	I2S_TX = (1 << 19),
	I2S_RX = (1 << 17),
	I2S_TxRx = (1 << 19 |1<< 17),
}I2S_IntrSource;

#ifdef S3C6410
typedef enum
{
	I2S_Tx0 = 0,
	I2S_Tx1 = 1,
	I2S_Tx2 = 2,
	I2S_AllTx = 3,
}I2S_DCE;

typedef enum
{
	NoDiscard 	 = 0,
	Discard15to0	 = 1,
	Discard31to16 = 2
}I2S_CDD;
#endif



#define ENABLE						(1)
#define DISABLE						(0)

#define ACTIVE						(1)
#define INACTIVE						(0)

#define PAUSE						(1)
#define PLAY							(0)

#define FLUSH						(1)
#define NON_FLUSH					(0)

#define I2S_CONNUM					(3)

#define WRDATA						(1)
#define POLLACK     					(2)
#define RDDATA						(3)
#define SETRDADDR					(4)

#define I2S_MODE_PLAY				0
#define I2S_MODE_RECORD_MICIn 		1
#define I2S_MODE_RECORD_LineIn		2

#define I2S_STATUS_PLAY				0
#define I2S_STATUS_RECORD			1

#define I2S_DMAC0_REC_COUNT		0x40
#define I2S_DMAC1_PLAY_COUNT		0x40
#define I2S_DMA_TRANSFER_SIZE		0xff0


#define I2S_I2C_BUF_SIZE				0x20
#define I2S_I2C_WRDATA				(1)
#define I2S_I2C_POLLACK 				(2)
#define I2S_I2C_RDDATA				(3)
#define I2S_I2C_SETRDADDR			(4)

typedef struct
{
	//PUBLIC
		// SMDK Configuration
		AudioCodec			m_uCodec;
		CodecPort			m_eLine;		
		//IP Operation
		PCMWordLength		m_eWordLength;	
		I2S_CLKSRC			m_eCLKSRC;	
		OPMode				m_eOpMode;	
		I2S_IFMode			m_eIFMode;
		I2S_LRCLKPolarity		m_eLRCLKPolarity;
		SerialDataFormat		m_eDataFormat;
		I2S_RFS				m_eRFS;
		I2S_BFS				m_eBFS;	
		#ifdef S3C6410
		I2S_DCE				m_eDCE;
		I2S_CDD				m_eFifo1CDD;
		I2S_CDD				m_eFifo2CDD;
		#endif
		//DMA Unit
		DMA_UNIT 			m_eDmaUnit;		
		//Sample Rate
		u32					m_uSamplingRate;	
		//Address
		u32*				m_pI2SRxAddr;
		u32*				m_pI2STxAddr;
		s32					m_sI2SRxSize;
		s32					m_sI2STxSize;
	//PRIVATE
		//Buffer
		u32*				m_pMemI2SRx;		
		u32*				m_pMemI2STx;	
		s32 					m_sI2SRxPointer;
		s32 					m_sI2STxPointer;
		//DMA Unit
		u32 					m_uNumDma;		
		//Tx DMA Request Channel
		DMAC 				m_oI2STxDma;	
		DMA_CH 			m_eDmaTxCh;
		//Rx DMA Request Channel
		DMAC 				m_oI2SRxDma;	
		DMA_CH				m_eDmaRxCh;
		//Private Global Variable
		u8					m_usI2SRxDone;
		u8					m_usI2STxDone;					
		
		//PROTECT	
}I2S_Infor;

typedef struct I2StestFuncMenu {
	void (*func)(AUDIO_PORT); 
	const char *desc;
} I2StestFuncMenu;

/*---------------------------------- APIs of general I2S ---------------------------------*/


void I2S_SetDMAUnit(AUDIO_PORT, DMA_UNIT);
u8 I2S_SetDMACh(AUDIO_PORT, I2S_IFMode,DMA_CH);
void I2S_InitDMA(AUDIO_PORT, I2S_IFMode);
void I2S_DMAStop(AUDIO_PORT, I2S_IFMode);
void I2S_DMAIntrClr(AUDIO_PORT ePort, I2S_IFMode eIFMode);

void I2S_SetIntrDone(AUDIO_PORT ePort, I2S_IFMode eCh, u8 usBool);
u8 I2S_GetIntrDone(AUDIO_PORT ePort, I2S_IFMode eCh);
//Memory Buffer
void I2S_InitBuffer(AUDIO_PORT, I2S_IFMode eCh, u32* pAddr, u32 uDataSize);
s32 I2S_PutDataMem(AUDIO_PORT ePort, I2S_IFMode eCh, u32* pData);
s32 I2S_PopDataMem(AUDIO_PORT ePort, I2S_IFMode eCh, u32* pData);


u32 I2S_Init(AUDIO_PORT);
void I2S_InitPort(AUDIO_PORT);
void I2S_SetCDCLKPort(AUDIO_PORT);
void I2S_ClosePort(AUDIO_PORT);
void I2S_CloseCDCLKPort(AUDIO_PORT);
// V0.1
void I2S_SetCDCLKOut(AUDIO_PORT ePort, I2S_CLKSRC eCLKSRC, u32 uSampleRate, I2S_RFS eRFSDivider);

/*---------------------------------- APIs of rI2SCON ---------------------------------*/
void I2SCON_ActiveIF(AUDIO_PORT, u8);
void I2SCON_ActiveDMA(AUDIO_PORT, I2S_IFMode, u8);
void I2SCON_PauseDMA(AUDIO_PORT ePort, I2S_IFMode eIFMode, u8 ucPause);
void I2SCON_PauseIF(AUDIO_PORT ePort, I2S_IFMode eIFMode, u8 ucPause);
void I2SCON_EnableIntr(AUDIO_PORT ePort, I2S_IntrSource rhs_eISource, u8 ucActive);
I2S_IFMode I2SCON_ChkInterrupt(AUDIO_PORT ePort);
void I2SCON_ClrOverIntr(AUDIO_PORT ePort);
void I2SCON_ClrUnderIntr(AUDIO_PORT ePort);
u8 I2SCON_ChkFIFOEmpty(AUDIO_PORT, I2S_IFMode);
u8 I2SCON_ChkFIFOFull(AUDIO_PORT, I2S_IFMode);
u8 I2SCON_ChkExtFIFOEmpty(AUDIO_PORT ePort, I2S_DCE eFifo);
u8 I2SCON_ChkExtFIFOFull(AUDIO_PORT ePort, I2S_DCE eFifo);
/*---------------------------------- APIs of rI2SMOD ---------------------------------*/
void I2SMOD_SetMode(AUDIO_PORT, PCMWordLength, I2S_CLKSRC, I2S_IFMode, OPMode, I2S_LRCLKPolarity, SerialDataFormat, I2S_RFS, I2S_BFS);
void I2SMOD_SetBLC(AUDIO_PORT, PCMWordLength);
PCMWordLength I2SMOD_GetBLC(AUDIO_PORT);
void I2SMOD_SetCLKSource(AUDIO_PORT, I2S_CLKSRC);
void I2SMOD_SetInterface(AUDIO_PORT, I2S_IFMode);
void I2S_SetInterface(AUDIO_PORT, I2S_IFMode);
I2S_IFMode I2SMOD_GetInterface(AUDIO_PORT);
void I2SMOD_SetOPMode(AUDIO_PORT, OPMode);
OPMode I2SMOD_GetOPMode(AUDIO_PORT);
void I2SMOD_SetLRPolarity(AUDIO_PORT, I2S_LRCLKPolarity);
I2S_LRCLKPolarity I2SMOD_GetLRPolarity(AUDIO_PORT);
void I2SMOD_SetInterfaceFormat(AUDIO_PORT, SerialDataFormat);
SerialDataFormat I2SMOD_GetDataFormat(AUDIO_PORT);
void I2SMOD_SetRFS(AUDIO_PORT, I2S_RFS);
I2S_RFS I2SMOD_GetRFS(AUDIO_PORT);
void I2SMOD_SetBFS(AUDIO_PORT, I2S_BFS);
I2S_BFS I2SMOD_GetBFS(AUDIO_PORT);
void I2SMOD_SetDCE(AUDIO_PORT ePort, I2S_DCE eDCE);
void I2SMOD_SetCDD(AUDIO_PORT ePort, I2S_DCE eDCE, I2S_CDD eCDD);


/*---------------------------------- APIs of rI2SFIC ---------------------------------*/
void I2SFIC_AutoFlush(AUDIO_PORT, I2S_IFMode);
u32 I2SFIC_GetFIFOLevel(AUDIO_PORT, I2S_IFMode);
/*---------------------------------- APIs of rI2SPSR ---------------------------------*/
void I2SPSR_SetPrescaler(AUDIO_PORT ePort, u32 rhs_uPrsVal);
void I2SPSR_ActivePRS(AUDIO_PORT ePort, u8 uActive);
void I2SPSR_PutPRSValue(AUDIO_PORT ePort, u32 rhs_uPrsVal);
/*---------------------------------- APIs of rI2STXD ---------------------------------*/
void I2STXD_PutData(AUDIO_PORT, u32);
u32 I2STXD_GetData(AUDIO_PORT);
/*---------------------------------- APIs of rI2SRXD ---------------------------------*/
void I2SRXD_PutData(AUDIO_PORT, u32);
u32 I2SRXD_GetData(AUDIO_PORT);
/*---------------------------------- ISR Routines ---------------------------------*/
void __irq Isr_I2SDmaRestart(void);
void __irq Isr_I2SDmaDone(void);
void I2S_DMARestart(AUDIO_PORT ePort, I2S_IFMode eCh);
void I2S_DMADone(AUDIO_PORT ePort, I2S_IFMode eCh);


void __irq ISR_I2S(void);
void __irq ISR_I2SOverrunTransfer(void);
void __irq ISR_I2SUnderrunTransfer(void);



/*---------------------------------- APIs of Clock ---------------------------------*/
void I2S_SetAudioCLK(AUDIO_PORT ePort, I2S_CLKSRC eClkSrc);
double I2S_SetEPLL(AUDIO_PORT ePort, double uTargetClk);
u32 I2S_GetPRSVal(AUDIO_PORT ePort, u32 uSourceCLK, u32 uTargetCLK);
I2S_Infor* I2S_GetInfor(AUDIO_PORT ePort);
void I2S_SetI2SInfor(AUDIO_PORT, I2S_Infor*);
u8 I2S_CpyI2SInfor(AUDIO_PORT, u32 *);

void	I2S_DmaStart(AUDIO_PORT ePort, I2S_IFMode eCh, u8 uRepeat);
void I2S_DmaStop(AUDIO_PORT ePort, I2S_IFMode eCh);
#ifdef __cplusplus
}
#endif

#endif /*__I2S_H__*/



